package com.compty.paint.service.impl;

import java.util.List;
import java.util.Map;

import com.compty.core.framework.util.DateUtil;
import com.compty.core.hibernate.HibernateEntityDao;
import com.compty.paint.domain.AdvanceLogs;
import com.compty.paint.domain.CustomerInfo;
import com.compty.paint.domain.Delivery;
import com.compty.paint.domain.DeliveryItem;
import com.compty.paint.domain.Order;
import com.compty.paint.domain.OrderLog;
import com.compty.paint.domain.PaymentLog;
import com.compty.paint.domain.support.OrderStatus;
import com.compty.paint.manager.AdvanceLogsManager;
import com.compty.paint.manager.CustomerInfoManager;
import com.compty.paint.manager.DeliveryItemManager;
import com.compty.paint.manager.DeliveryManager;
import com.compty.paint.manager.OrderLogManager;
import com.compty.paint.manager.OrderManager;
import com.compty.paint.manager.PaymentLogManager;
import com.compty.paint.service.UserServiceFactory;

/**
 * 订单业务流程
 */
public class OrderFlowManager extends HibernateEntityDao<Order>{
	
	private OrderManager orderManager;
	private OrderLogManager orderLogManager;
	
	private PaymentLogManager paymentLogManager;
	private AdvanceLogsManager advanceLogsManager;
	private DeliveryManager deliveryManager;
	private DeliveryItemManager deliveryItemManager;
	
	private CustomerInfoManager memberManager;

	/**
	 * 支付
	 */
	public void pay(PaymentLog payment) {

		if(payment== null ) throw new  IllegalArgumentException("param paymentLog is NULL");
		if(payment.getOrder()== null ) throw new  IllegalArgumentException("param PaymentLog's order_id is NULL");
		if(payment.getMoney()== null ) throw new  IllegalArgumentException("param  PaymentLog's money is NULL");
		Order order = this.orderManager.get(payment.getOrder().getId());
		checkDisabled(order);
		if(order.getPay_status().intValue() == OrderStatus.PAY_YES ){
			if(logger.isDebugEnabled()){
				logger.debug("订单["+order.getSequenceNo()+"]支付状态为[已经支付]，不能再对其进行支付操作");
			}
			throw new IllegalStateException("订单["+order.getSequenceNo()+"]支付状态为[已经支付]，不能再对其进行支付操作");
		}
		
		if(logger.isDebugEnabled()){
			logger.debug("支付订单:"+order.getId());
		}
		
		if(order.getCustomerInfo() != null){
			//扣除用户预存款
			if(payment.getPay_type().trim().equals("deposit")){	
				this.saveMoney(order, payment);
			}
		}		
		
		double m =order.getOrder_amount();// 订单总额
		double nm = payment.getMoney();// 当前付款金额
		double om = order.getPaymoney() == null ? 0:order.getPaymoney();// 已收金额
		
		double sm = nm + om;
		int payStatus = 0;
		if (sm < m)
			payStatus = OrderStatus.PAY_PARTIAL_PAYED;// 部分支付
		if (sm >= m)
			payStatus = OrderStatus.PAY_YES;// 已付款
		
		payment.setType(1);
		payment.setStatus(1);
		payment.setCreate_time(DateUtil.getNow());
		payment.setCustomerInfo(order.getCustomerInfo());
		paymentLogManager.save(payment);
		
		if(logger.isDebugEnabled()){
			logger.debug("更新订单状态["+OrderStatus.ORDER_PAY+"],支付状态["+payStatus+ "]");
		}
		
		order.setStatus(OrderStatus.ORDER_PAY);
		order.setPay_status(payStatus);
		order.setPaymoney(order.getPaymoney()+payment.getMoney());
		super.save(order);
		
		this.log(payment.getOrder(), "支付订单"+order.getId()+"，金额"+ payment.getMoney(), null, "管理员");
	}
	
	
	/**
	 * 更新会员预存款
	 */
	private void saveMoney(Order order, PaymentLog payment){
		if(logger.isDebugEnabled()){
			logger.debug("扣除用户["+order.getCustomerInfo().getId()+"]预存款:"+payment.getMoney());
		}
		CustomerInfo member = this.memberManager.get(order.getCustomerInfo().getId());
		if(member.getAdvance().compareTo(payment.getMoney()) <0){
			if(logger.isDebugEnabled()){
				logger.debug("用户预存款["+member.getAdvance().doubleValue()+"]不足,需要支付["+payment.getMoney().doubleValue() +"]");
			}					
			throw new RuntimeException("用户预存款["+member.getAdvance().doubleValue()+"]不足,需要支付["+payment.getMoney().doubleValue() +"]");
		}
		
		Double advance = member.getAdvance();
		advance = advance - payment.getMoney();
		member.setAdvance(advance);
		memberManager.save(member);

		
		//既然是用预存款支付，则应加到预存款日志中
		member = this.memberManager.get(order.getCustomerInfo().getId());//再取回预存款的数值
		AdvanceLogs advanceLogs = new AdvanceLogs();
		advanceLogs.setMember_id(order.getCustomerInfo().getId());
		advanceLogs.setDisabled("false");
		advanceLogs.setMtime(order.getModifyTime());
		advanceLogs.setImport_money(null);
		advanceLogs.setExplode_money(payment.getMoney());
		advanceLogs.setMember_advance(member.getAdvance());
		advanceLogs.setShop_advance(member.getAdvance());// 此字段很难理解
		advanceLogs.setMoney(0-payment.getMoney());
		advanceLogs.setMessage("预存款支付：订单号{"+payment.getOrder().getId()+"}");
		advanceLogs.setOrder_id(payment.getOrder().getId());
		advanceLogs.setMemo("预存款支付");
		advanceLogsManager.save(advanceLogs);
		//预存款日志完成
		
		
		//更新session中预存款和积分的值
		CustomerInfo sessionMember = UserServiceFactory.getUserService().getCurrentMember();
		if(sessionMember!=null){
			sessionMember.setAdvance(sessionMember.getAdvance()-payment.getMoney());
		}		
	}
	
	/**
	 * 退款
	 */
	public void refund(PaymentLog payment) {
		if(payment== null ) throw new  IllegalArgumentException("param paymentLog is NULL");
		if(payment.getOrder()== null ) throw new  IllegalArgumentException("param PaymentLog's order_id is NULL");
		if(payment.getMoney()== null ) throw new  IllegalArgumentException("param PaymentLog's money is NULL");
		Order order = this.orderManager.get(payment.getOrder().getId());
		checkDisabled(order);
		if(order.getPay_status().intValue() == OrderStatus.PAY_CANCEL ){
			if(logger.isDebugEnabled()){
				logger.debug("订单["+order.getSequenceNo()+"]支付状态为[已经退款]，不能再对其进行退款操作");
			}
			throw new IllegalStateException("订单["+order.getSequenceNo()+"]支付状态为[已经退款]，不能再对其进行退款操作");
		}
		
		if(logger.isDebugEnabled()){
			logger.debug("订单:"+order.getId()+"退款");
		}
		
		double m =order.getOrder_amount();// 订单总额
		double nm = payment.getMoney();// 当前付款金额
		double om = order.getPaymoney();// 已收金额
		

		int payStatus = 0;
		if (nm == om)
			payStatus = OrderStatus.PAY_CANCEL;// 已退款
		if (nm < om)
			payStatus = OrderStatus.PAY_PARTIAL_REFUND;// 部分退款
		if (nm > om) {
			if(logger.isDebugEnabled()){
				logger.debug("退款金额["+nm+"]超过订单支付金额["+m+"]");
			}			
			throw new RuntimeException("退款金额["+nm+"]超过订单支付金额["+m+"]");
		}
		payment.setType(2);
		payment.setStatus(1);
		payment.setCreate_time(DateUtil.getNow());
		payment.setCustomerInfo(order.getCustomerInfo());
		paymentLogManager.save(payment);
 
			
		if(logger.isDebugEnabled()){
			logger.debug("更新订单状态["+OrderStatus.ORDER_CANCEL_PAY+"],支付状态["+payStatus+ "]");
		}		
		
		order.setStatus(OrderStatus.ORDER_CANCEL_PAY);
		order.setPay_status(payStatus);
		order.setPaymoney(order.getPaymoney()- payment.getMoney());
		orderManager.save(order);
		//返还用户预存款
		//if(payment.getPay_method().trim().equals("预存款支付")){
		//上面有逻辑错误，应该是Pay_type对应的是预存款（deposit），而不是Pay_method（它对应的是Pay_type为在线支付(online)时的支付方式）
		if(payment.getPay_type().trim().equals("deposit")){	
			if(order.getCustomerInfo()!=null){
				if(logger.isDebugEnabled()){
					logger.debug("返还用户["+order.getCustomerInfo().getIdCard()+"]预存款:"+payment.getMoney());
				}
				Long member_id = order.getCustomerInfo().getId();
				CustomerInfo member = memberManager.get(member_id);
				member.setAdvance(member.getAdvance()+payment.getMoney());
				memberManager.save(member);
				//既然是用预存款支付，则应加到预存款日志中
				member = this.memberManager.get(payment.getCustomerInfo().getId());//再取回预存款的数值
				AdvanceLogs advanceLogs = new AdvanceLogs();
				advanceLogs.setMember_id(payment.getCustomerInfo().getId());
				advanceLogs.setDisabled("false");
				advanceLogs.setMtime(DateUtil.getNow());
				advanceLogs.setImport_money(payment.getMoney());
				advanceLogs.setExplode_money(null);
				advanceLogs.setMember_advance(member.getAdvance());
				advanceLogs.setShop_advance(member.getAdvance());// 此字段很难理解
				advanceLogs.setMoney(payment.getMoney());
				advanceLogs.setMessage("预存款退款：订单号{"+payment.getOrder().getId()+"}");
				advanceLogs.setOrder_id(payment.getOrder().getId());
				advanceLogs.setMemo("预存款退款");
				advanceLogsManager.save(advanceLogs);
				//预存款日志完成
			}
		}
		
		this.log(payment.getOrder(), "订单退款，金额"+ payment.getMoney(), null, "管理员");
		
	}
	
	/**
	 * 记录订单操作日志
	 * @param order 订单
	 * @param message
	 * @param op_id
	 * @param op_name
	 */
	private void log(Order order,String message,Integer op_id,String op_name){
		OrderLog orderLog = new OrderLog();
		orderLog.setMessage(message);
		orderLog.setOp_id(op_id);
		orderLog.setOp_name(op_name);
		orderLog.setOp_time(DateUtil.getNow());
		orderLog.setOrder(order);
		orderLogManager.save(orderLog);
	}

	/**
	 * 发货
	 */
	public void shipping(Delivery delivery, List<DeliveryItem> itemList,List<DeliveryItem> giftItemList) {
		
		if(delivery== null) throw new  IllegalArgumentException("param delivery is NULL");
		if(itemList== null) throw new  IllegalArgumentException("param itemList is NULL");
		if(delivery.getOrder() == null )  throw new IllegalArgumentException("param order id is null");
		
		if(delivery.getMoney()== null ) delivery.setMoney(0D);
		if(delivery.getProtect_price()==null) delivery.setProtect_price(0D);
		
		if(logger.isDebugEnabled()){
			logger.debug("订单["+delivery.getOrder()+"]发货");
		}
		
		Integer orderId = delivery.getOrder().getId() ;
		Order order = this.orderManager.get(orderId);
		checkDisabled(order);
		if(order.getShip_status().intValue() ==  OrderStatus.SHIP_YES){
			if(logger.isDebugEnabled()){
				logger.debug("订单["+order.getSequenceNo()+"]状态已经为【已发货】，不能再对其进行发货操作");
			}			
			throw new IllegalStateException("订单["+order.getSequenceNo()+"]状态已经为【已发货】，不能再对其进行发货操作");
		}
		
		delivery.setType(1);
		delivery.setCustomerInfo(order.getCustomerInfo());
		delivery.setCreate_time(DateUtil.getNow());
		deliveryManager.save(delivery);
		
		int shipStatus = OrderStatus.SHIP_YES;
		
		//处理商品发货项
		int goodsShipStatus = this.processGoodsShipItem(orderId, delivery, itemList);
		shipStatus=goodsShipStatus;
		
		//如果发货状态不为全部发货即为部分发货
		shipStatus=shipStatus==OrderStatus.SHIP_YES?OrderStatus.SHIP_YES :OrderStatus.SHIP_PARTIAL_SHIPED;
		
		if(logger.isDebugEnabled()){
			logger.debug("更新订单["+ orderId+"]状态["+OrderStatus.ORDER_SHIP+"]，发货状态["+shipStatus+"]");
		}			
		//更新订单状态为已发货
		order.setStatus( OrderStatus.ORDER_SHIP);
		order.setShip_status(shipStatus);
		orderManager.save(order);
		this.log(delivery.getOrder(), "订单发货，物流单据号："+ delivery.getLogi_no(), null, "管理员");
		
	}
	
	
	/**
	 * 处理商品退货
	 * @param orderId 订单id
	 * @param delivery_id 发货单id
	 * @param orderItemList 订单商品货物 {@link IOrderManager#listGoodsItems(Integer)}
	 * @param itemList 由用户表单读取的退货数据
	 * @return 商品退货状态
	 */
	@SuppressWarnings("unchecked")
	private int processGoodsReturnItem(Integer orderId,Delivery delivery,List<DeliveryItem> itemList){
		List<Map> orderItemList = this.orderManager.listGoodsItems(orderId);//此订单的相关商品货品
		int shipStatus = OrderStatus.SHIP_CANCEL;
		for(DeliveryItem item: itemList){
			
			if(item.getGoods_id() == null) throw new IllegalArgumentException(item.getName()+" goods id is  NULL");
			if(item.getProduct_id() == null) throw new IllegalArgumentException(item.getName()+" product id is  NULL");
			if(item.getNum()== null) throw new IllegalArgumentException(item.getName()+" num id is  NULL");
			
			if(logger.isDebugEnabled()){
				logger.debug("检测item["+item.getName()+"]退货数量是否合法");
			}			
			//检查退货数量是否合法，并得到这项的退货状态
			int itemStatus = this.checkGoodsReturnNum(orderItemList, item);
			
			//全部为退货完成则订单的发货状态为退货完成
			shipStatus=( shipStatus== OrderStatus.SHIP_CANCEL && itemStatus==OrderStatus.SHIP_CANCEL)?OrderStatus.SHIP_CANCEL:itemStatus;
			
			item.setDelivery(delivery);
			//记录退货明细
			deliveryItemManager.save(item);
			
			//更新退货量
//			baseDaoSupport.execute("update order_items set ship_num=ship_num-? where order_id=? and spec_id=?", item.getNum(),orderId,item.getProduct_id());
			
			//更新库存量
//			baseDaoSupport.execute("update goods set store=store+? where goods_id=?", item.getNum(),item.getGoods_id());
//			baseDaoSupport.execute("update product set store=store+? where product_id=?", item.getNum(),item.getProduct_id());
			
		}		
		return shipStatus;
	}

	/**
	 * 处理商品发货项
	 * @param orderId
	 * @param delivery_id
	 * @param itemList
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private int processGoodsShipItem(Integer orderId,Delivery delivery, List<DeliveryItem> itemList){
		
		//此订单的相关货品
		List<Map> orderItemList = this.orderManager.listGoodsItems(orderId);
		int shipStatus = OrderStatus.SHIP_YES;
		
		for(DeliveryItem item: itemList){
			
			if(item.getGoods_id() == null) throw new IllegalArgumentException(item.getName()+" goods id is  NULL");
			if(item.getProduct_id() == null) throw new IllegalArgumentException(item.getName()+" product id is  NULL");
			if(item.getNum()== null) throw new IllegalArgumentException(item.getName()+" num id is  NULL");
			
			if(logger.isDebugEnabled()){
				logger.debug("检测item["+item.getName()+"]发货数量是否合法");
			}			
			//检查发货数量是否合法，并得到这项的发货状态
			int itemStatus = this.checkGoodsShipNum(orderItemList, item);
			
			//全部为发货完成则订单的发货状态为发货完成
			shipStatus=( shipStatus== OrderStatus.SHIP_YES && itemStatus==OrderStatus.SHIP_YES)?OrderStatus.SHIP_YES:itemStatus;
			
			
			if(logger.isDebugEnabled()){
				logger.debug("检测item["+item.getName()+"]库存");
			}				
			
			item.setDelivery(delivery);
			//记录发货明细
			deliveryItemManager.save(item);
			
			//更新发货量
//			baseDaoSupport.execute("update order_items set ship_num=ship_num+? where order_id=? and spec_id=?", item.getNum(),orderId,item.getProduct_id());
			
			//更新库存量
//			baseDaoSupport.execute("update goods set store=store-? where goods_id=?", item.getNum(),item.getGoods_id());
//			baseDaoSupport.execute("update product set store=store-? where product_id=?", item.getNum(),item.getProduct_id());
			if(this.logger.isDebugEnabled()){
				this.logger.debug("更新"+ item.getName()+"["+ item.getProduct_id()+","+item.getGoods_id()+"-["+item.getNum()+"]");
			}
		}
		
		
		return shipStatus;
	}
	

	/**
	 * 退货
	 */
	
	public void returned(Delivery delivery, List<DeliveryItem> itemList,List<DeliveryItem> giftItemList) {
		if(delivery== null) throw new  IllegalArgumentException("param delivery is NULL");
		if(itemList== null) throw new  IllegalArgumentException("param itemList is NULL");
		if(delivery.getOrder() == null )  throw new IllegalArgumentException("param order id is null");
		
		if(delivery.getMoney()== null ) delivery.setMoney(0D);
		if(delivery.getProtect_price()==null) delivery.setProtect_price(0D);
		
		if(logger.isDebugEnabled()){
			logger.debug("订单["+delivery.getOrder()+"]退货");
		}
		
		Integer orderId = delivery.getOrder().getId();
		Order order = this.orderManager.get(orderId);
		checkDisabled(order);
		if(order.getShip_status().intValue() ==  OrderStatus.SHIP_CANCEL){
			if(logger.isDebugEnabled()){
				logger.debug("订单["+order.getSequenceNo()+"]状态已经为【已退货】，不能再对其进行退货操作");
			}			
			throw new IllegalStateException("订单["+order.getSequenceNo()+"]状态已经为【已退货】，不能再对其进行退货操作");
		}
		
		delivery.setType(2);
		delivery.setCustomerInfo(order.getCustomerInfo());
		delivery.setCreate_time(DateUtil.getNow());
		deliveryManager.save(delivery);
	
		
		//处理退货状态
		int shipStatus = OrderStatus.SHIP_CANCEL;
		int goodsShipStatus = this.processGoodsReturnItem(orderId, delivery, itemList);
		shipStatus= goodsShipStatus;
		
		//如果退货完成则 退货状态为退货完成，否则为部分退货
		shipStatus = shipStatus==OrderStatus.SHIP_CANCEL ?OrderStatus.SHIP_CANCEL:OrderStatus.SHIP_PARTIAL_CANCEL;
		
		if(logger.isDebugEnabled()){
			logger.debug("更新订单["+ orderId+"]状态["+OrderStatus.ORDER_CANCEL_SHIP+"]，发货状态["+shipStatus+"]");
		}			
		//更新订单状态为已退货
		order.setStatus(OrderStatus.ORDER_CANCEL_SHIP);
		order.setShip_status(shipStatus);
		orderManager.save(order);
		this.log(delivery.getOrder(), "订单退货，物流单据号："+ delivery.getLogi_no(), null, "管理员");		
	}
	
	
	/**
	 * 检查退货量是否合法，并且计算退货状态
	 * @param orderItemList 购买的订单货物信息 @see {@link IOrderManager#listGoodsItems(Integer)}
	 * @param item 某一个发货项
	 * @return  
	 */
	@SuppressWarnings("unchecked")
	private int checkGoodsReturnNum(List<Map> orderItemList ,DeliveryItem item){
		
		int status =OrderStatus.SHIP_YES;
		for(Map orderItem:orderItemList){
			
			if( Integer.valueOf( orderItem.get("spec_id").toString()).compareTo(item.getProduct_id()) == 0){
			
				Integer shipNum = Integer .valueOf( orderItem.get("ship_num").toString() ); //已经发货量
				if(shipNum < item.getNum() ){ //已发货量小于本次 退货量
					if(logger.isDebugEnabled()){
						logger.debug("商品["+item.getName()+"]本次发货量["+item.getNum() +"]超出已发货量["+shipNum+"]");
					}						
					throw new RuntimeException("商品["+item.getName()+"]本次发货量["+item.getNum() +"]超出已发货量["+shipNum+"]");
				}
				if(shipNum.compareTo( item.getNum())==0 ){ //已发货量等于本次退货量，状态为已退货
					status= OrderStatus.SHIP_CANCEL;
				}
				
				if(shipNum >item.getNum()){ //已发货量大于本次退货量,状态为部分退货
					status= OrderStatus.SHIP_PARTIAL_CANCEL;
				}	
			}
		}
		return status;
	}
	
	/**
	 * 完成
	 */
	
	public void complete(Integer orderId) {
		if(orderId== null ) throw new  IllegalArgumentException("param orderId is NULL");
		Order order = orderManager.get(orderId);
		order.setStatus(OrderStatus.ORDER_COMPLETE);
		orderManager.save(order);
	}
	/**
	 * 作废
	 */
	
	public void cancel(Integer orderId) {
		if(orderId== null ) throw new  IllegalArgumentException("param orderId is NULL");
		Order order = orderManager.get(orderId);
		order.setStatus(OrderStatus.ORDER_CANCELLATION);
		orderManager.save(order);
	}

	
	/**
	 * 检查发货量是否合法，并且计发货状态
	 * @param orderItemList 购买的订单货物信息
	 * @param item 某一个发货项
	 * @return  
	 */
	@SuppressWarnings("unchecked")
	private int checkGoodsShipNum(List<Map> orderItemList ,DeliveryItem item){
		
		int status =OrderStatus.SHIP_NO;
		for(Map orderItem:orderItemList){
			
			if( Integer.valueOf( orderItem.get("spec_id").toString()).compareTo(item.getProduct_id())==0){
				
				Integer num = Integer .valueOf( orderItem.get("num").toString() ); //总购买量
				Integer shipNum = Integer .valueOf( orderItem.get("ship_num").toString() ); //已经发货量
				if(num<item.getNum() + shipNum){ //总购买量小于总发货量
					if(logger.isDebugEnabled()){
						logger.debug("商品["+item.getName()+"]本次发货量["+item.getNum() +"]后超出用户购买量["+num+"],此商品已经发货["+shipNum+"]");
					}						
					throw new RuntimeException("商品["+item.getName()+"]本次发货量["+item.getNum() +"]后超出用户购买量["+num+"],此商品已经发货["+shipNum+"]");
				}
				if(num.compareTo(item.getNum() + shipNum)==0){ //总购买量等于总购买量
					status= OrderStatus.SHIP_YES;
				}
				
				if(num>item.getNum() + shipNum){ //总购买量大于总购买量
					status= OrderStatus.SHIP_PARTIAL_SHIPED;
				}	
			}
		}
		return status;
		
	}

	/**
	 * 检查订单状态是否在可操作状态
	 * @param order
	 * @throws IllegalStateException 如果订单是完成或作废状态
	 */
	private void checkDisabled(com.compty.paint.domain.Order order){
		if(order.getStatus().intValue() ==  OrderStatus.ORDER_COMPLETE || order.getStatus().intValue() ==  OrderStatus.ORDER_CANCELLATION)
			throw new IllegalStateException("订单已经完成或作废，不能完成操作");
	}


	public void setOrderManager(OrderManager orderManager) {
		this.orderManager = orderManager;
	}


	public void setOrderLogManager(OrderLogManager orderLogManager) {
		this.orderLogManager = orderLogManager;
	}


	public void setPaymentLogManager(PaymentLogManager paymentLogManager) {
		this.paymentLogManager = paymentLogManager;
	}


	public void setAdvanceLogsManager(AdvanceLogsManager advanceLogsManager) {
		this.advanceLogsManager = advanceLogsManager;
	}


	public void setDeliveryManager(DeliveryManager deliveryManager) {
		this.deliveryManager = deliveryManager;
	}


	public void setDeliveryItemManager(DeliveryItemManager deliveryItemManager) {
		this.deliveryItemManager = deliveryItemManager;
	}


	public void setMemberManager(CustomerInfoManager memberManager) {
		this.memberManager = memberManager;
	}

}
